export default class Outline {
  constructor ({
    sandbox,
    params = {},
    color
  }) {
    this.sandbox = sandbox

    const { renderer, scene, camera } = this.sandbox
    this.sandbox = sandbox
    this._color = color
    this._width = this.sandbox._width
    this._height = this.sandbox._height
    this._params = Object.assign({
      edgeStrength: 3, // 轮廓的强度 3.0
      edgeGlow: 0, // 轮廓的发光强度 0.0
      edgeThickness: 2, // 轮廓的厚度 1.0
      pulsePeriod: 0, // 轮廓的闪烁速度 0.0
      visibleEdgeColor: this._color, // 显示颜色  0x00ffff #FF7C02 #e91010 #24ffcb
      hiddenEdgeColor: this._color // 被遮蔽颜色
    }, params)

    this.composer = new GC.EffectComposer(renderer)
    this.composer.renderTarget1.samples = 8
    this.composer.renderTarget2.samples = 8
    this.renderPass = new GC.RenderPass(scene, camera)
    // this.renderPass.renderToScreen = false
    this.composer.addPass(this.renderPass)
    this.sandbox.enablePostProcessing = true

    this.outlinePass = new GC.OutlinePass(
      new GC.Vector2(this._width, this._height),
      scene,
      camera
    )

    //
    // this.outlinePass.setSize((this._width) / 10, (this._height) / 10) // 减少 OutlinePass 的分辨率
    this.outlinePass.edgeStrength = this._params.edgeStrength
    this.outlinePass.edgeGlow = this._params.edgeGlow
    this.outlinePass.edgeThickness = this._params.edgeThickness
    this.outlinePass.pulsePeriod = this._params.pulsePeriod
    this.outlinePass.visibleEdgeColor.set(this._params.visibleEdgeColor)
    this.outlinePass.hiddenEdgeColor.set(this._params.hiddenEdgeColor)

    this.composer.addPass(this.outlinePass)
    this.composer.addPass(new GC.OutputPass())

    this.sandbox.renderCalls.push(this.render.bind(this))
    this.sandbox.sizeCalls.push(this.updateWindow.bind(this))
  }

  // add(value) {
  //   if (Array.isArray(value)) {
  //     this.outlinePass.selectedObjects = [...value]
  //   } else {
  //     this.outlinePass.selectedObjects = value ? [value] : []
  //   }
  //   // this.outlinePass.selectedObjects.push(value)
  // }
  add (value) {
    if (!value) return this // 空值快速返回

    const addList = Array.isArray(value) ? value : [value]
    const selectedSet = new Set(this.outlinePass.selectedObjects)

    addList.forEach(obj => obj && selectedSet.add(obj)) // 去重添加

    this.outlinePass.selectedObjects = Array.from(selectedSet) // 链式友好
  }

  remove (value) {
    if (!this.outlinePass.selectedObjects.length) return

    const toRemove = new Set(
      Array.isArray(value) ? value : value ? [value] : []
    )

    this.outlinePass.selectedObjects =
      this.outlinePass.selectedObjects.filter(obj => !toRemove.has(obj))
  }

  clear () {
    this.outlinePass.selectedObjects = []
  }

  render () {
    this.composer.render() //  必须要时刻刷新 composer.render()
    // if (this.outlinePass.selectedObjects.length > 0) {
    // }
  }

  updateWindow () {
    this.composer.setSize(this._width, this._height)
  }

  gui () {
    this.gui = new GC.GUI({ width: 300 })
    this.gui.add(this._params, 'edgeStrength', 0.01, 20).name('轮廓的强度').step(0.05).onChange(function (value) {
      this.outlinePass.edgeStrength = Number(value)
    }.bind(this))
    this.gui.add(this._params, 'edgeGlow', 0.0, 10).name('轮廓的发光强度').step(0.05).onChange(function (value) {
      this.outlinePass.edgeGlow = Number(value)
    }.bind(this))
    this.gui.add(this._params, 'edgeThickness', 0.0, 10).name('轮廓的厚度').step(0.05).onChange(function (value) {
      this.outlinePass.edgeThickness = Number(value)
    }.bind(this))
    this.gui.add(this._params, 'pulsePeriod', 0.0, 10).name('轮廓的闪烁速度').step(0.05).onChange(function (value) {
      this.outlinePass.pulsePeriod = Number(value)
    }.bind(this))
    const Configuration = function () {
      this.visibleEdgeColor = '#ffffff'
      this.hiddenEdgeColor = '#190a05'
    }
    const conf = new Configuration()
    this.gui.addColor(conf, 'visibleEdgeColor').name('可见轮廓的颜色').onChange(function (value) {
      this.outlinePass.visibleEdgeColor.set(value)
    }.bind(this))
    this.gui.addColor(conf, 'hiddenEdgeColor').name('不可见轮廓的颜色').onChange(function (value) {
      this.outlinePass.hiddenEdgeColor.set(value)
    }.bind(this))
  }

  destroy () {
    this.outlinePass.selectedObjects = []
    this.renderPass.dispose()
    this.composer.dispose()
    this.outlinePass.dispose()

    // 销毁render与窗口更新
    const renderIndex = this.sandbox.renderCalls.findIndex(this.render.bind(this))
    this.sandbox.renderCalls?.splice(renderIndex, 1)
    const index = this.sandbox.sizeCalls.findIndex(this.updateWindow.bind(this))
    this.sandbox.sizeCalls?.splice(index, 1)
    this.gui.destroy()
  }
}
